package Reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Test {

  public static void main(String[] args)throws Exception {

//    反射的第一步是获得字节码文件，3种方式
//    Class.forName("全限定类名")
    Class lover = Class.forName("Reflect.Lover");

//    当类已经是字节码文件时，就是自己获得自己
//    Class lover = Lover.class;

//    通过该类的实例获得字节码文件
//    Lover lover = new Lover();
//    Class lover = lover.class;

//    调用API
    System.out.println("全限定类名为：" + lover.getName());
    System.out.println("类名：" + lover.getSimpleName());
    System.out.println("当前类的类加载器：" + lover.getClassLoader());

//    获得所有构造函数
    Constructor[] constructors = lover.getConstructors();
    for (Constructor constructor1 : constructors) {
      System.out.println("结果为：" + constructor1);
    }

//   指定有参构造函数，通过有参构造函数来实例对象
//    Constructor constructor = lover.getConstructor(int.class, String.class);
//    Lover lover1 = (Lover) constructor.newInstance(23,"ospreay");

//    直接通过newInstance创造实例对象，使用的是无参构造器来实例对象
//    通过getDeclaredFields()获得所有字段
    Lover lover1 = (Lover) lover.newInstance();
    lover1.setAge(23);
    lover1.setName("ospreay");
    Field[] declaredFields = lover.getDeclaredFields();
    for (Field field : declaredFields) {
      field.setAccessible(true);
      System.out.println(field.get(lover1));
    }

//    调用方法，让方法透明
    Method method = lover.getDeclaredMethod("say",String.class);
    method.setAccessible(true);
//    方法调用使用invoke，第一个参数为类名，第二个参数为方法参数，若无可不写
    method.invoke(lover1,"嗯嗯");
  }
}
